package com.study.sequence.api.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.study.common.annotation.MyService;
import com.study.sequence.api.ISequencerviceApi;
import com.study.sequence.common.CommonConstract;
import com.study.sequence.dto.SequenceDTO;
import com.study.sequence.entity.BtSequence;
import com.study.sequence.service.IBtSequenceService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

/**
 * Created by 张波 on 2020/6/21.
 */
@MyService
@Component
public class SequencerviceApiImpl implements ISequencerviceApi {

    @Autowired
    private IBtSequenceService btSequenceService;

    @Override
    public SequenceDTO getSequence(String businessKey) {
        BtSequence btSequence = new BtSequence();
        businessKey = StringUtils.isBlank(businessKey) ? CommonConstract.DEFAULT_BUSINESS_KEY : businessKey;
        btSequence.setBusinessKey(businessKey);
        btSequence.setDelInd(CommonConstract.DEL_IND);
        btSequence = btSequenceService.getOne(new QueryWrapper<>(btSequence));
        if (null == btSequence) {
            /*序列不存在，创建新默认序列*/
            btSequence = createDefaultSequence(businessKey);
            btSequenceService.save(btSequence);
        }
        Integer value = this.flush(btSequence.getBusinessKey());
        SequenceDTO result = new SequenceDTO();
        BeanUtils.copyProperties(btSequence, result);
        result.setCurrentValue(value);
        return result;
    }


    /**
     * 构建默认sequence
     *
     * @return
     */
    private BtSequence createDefaultSequence(String businessKey) {
        BtSequence btSequence = new BtSequence();
        if (StringUtils.isBlank(businessKey)) {
            btSequence.setBusinessKey(CommonConstract.DEFAULT_BUSINESS_KEY);
        }
        btSequence.setBusinessKey(businessKey);
        btSequence.setValueSize(8);
        btSequence.setCurrentValue(0);
        btSequence.setStepValue(100);
        btSequence.setDelInd(CommonConstract.DEL_IND);
        btSequence.setCreateTime(LocalDateTime.now());
        btSequence.setUpdateTime(LocalDateTime.now());
        return btSequence;
    }

    private Integer flush(String businessKey) {
        BtSequence btSequence = null;
        Integer result = null;
        do {
            btSequence = getBtSequence(businessKey);
            if (btSequence == null) {
                throw new RuntimeException("未能获取到sequence规则对象");
            }
            result = btSequence.getCurrentValue();
        } while (!updateBtSequence(btSequence));
        return result;
    }

    private boolean updateBtSequence(BtSequence btSequence) {
        BtSequence where = new BtSequence();
        where.setId(btSequence.getId());
        where.setBusinessKey(btSequence.getBusinessKey());
        where.setCurrentValue(btSequence.getCurrentValue());
        btSequence.setCurrentValue(btSequence.getCurrentValue() + 1);
        btSequence.setUpdateTime(LocalDateTime.now());
        UpdateWrapper<BtSequence> wrapper = new UpdateWrapper<>(where);
        return btSequenceService.update(btSequence, wrapper);
    }

    private BtSequence getBtSequence(String businessKey) {
        BtSequence btSequence = new BtSequence();
        btSequence.setBusinessKey(businessKey);
        btSequence.setDelInd(CommonConstract.DEL_IND);
        btSequence = btSequenceService.getOne(new QueryWrapper<>(btSequence));
        return btSequence;
    }
}
